package com.jason.um.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import sun.security.internal.spec.TlsPrfParameterSpec;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;
import java.util.LinkedHashMap;

/**
 * @ClassName JWTUtil
 * @Description TODO
 * @Author Jason
 * @Date 2019/1/24 9:31
 * @Version 1.0
 **/
public class JWTUtil {

    private static final String APP_ID = "afclaidvadsvbasudifwye9129e8qdeoqaknf";
    // 假设为 项目名
    private static final String APP_SECRET = "cas9d012e012peqnd;anscpa9uw09e0qjdcan20y4012yr0qfcosa8yvc9shoczx87v9cz9xvyhoxzvy9";
    private String KEY_SING =  ""; //用於存放TOKEN的標誌,Redis
    // private LinkedHashMap<String, Object> pairs = new LinkedHashMap();//封装json的map

    public static final long MINUTE_TTL = 60*1000;  //millisecond
    public static final long HOURS_TTL = 60*60*1000;  //millisecond
    public static final long DAY_TTL = 12*60*60*1000;  //millisecond


    /**
     * 创建 jwt
     * @param id 主键 用于防止JWT被重发布
     * @param issuer 签发者的名称 可以设为项目名 springboot-seckill-server
     * @param subject jwt所面向的用户的值 一般设为用户姓名
     * @param audience 听众 请求来源
     * @param ttlMillis 有效时间
     * @return Token值
     * @throws Exception
     */
    //Sample method to construct a JWT
    public static String createJWT(String id, String subject, String issuer, String audience, long ttlMillis) {

        //The JWT signature algorithm we will be using to sign the token
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        
        //We will sign our JWT with our ApiKey secret
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary( APP_ID + APP_SECRET);
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

        //Let's set the JWT Claims
        JwtBuilder builder = Jwts.builder().setId(id)
                .setIssuedAt(now)
                .setSubject(subject)
                .setIssuer(issuer)
                .setAudience(audience)
                //不应使用在此时间戳之前获得的JWT。 此方法可将刷新之前的Token作废
                .setNotBefore(now)
                .signWith(signatureAlgorithm, signingKey);

        //if it has been specified, let's add the expiration
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp);
        }

        //Builds the JWT and serializes it to a compact, URL-safe string
        return builder.compact();
    }

    /**
     * 解密 jwt
     * @param jwt
     * @return
     * @throws Exception
     */
    //Sample method to validate and read the JWT
    public static Claims parseJWT(String jwt) {

        //This line will throw an exception if it is not a signed JWS (as expected)
        Claims claims = Jwts.parser()
                .setSigningKey(DatatypeConverter.parseBase64Binary(APP_ID + APP_SECRET))
                .parseClaimsJws(jwt).getBody();
        return claims;
    }

    public static String refreshJwt(String jwt) {
        Claims claims = parseJWT(jwt);
        return createJWT(StringIdGenerator.get(), claims.getSubject(), claims.getIssuer(), claims.getAudience(), DAY_TTL);
    }

}
